import _ from 'underscore';
import BaseCollection from './BaseCollection';

const OrderableCollection = BaseCollection.extend({
    comparator: 'order',
    initialize: function (options) {
        this.updateModelOrder(false);
    },
    updateModelOrder: function (sync) {
        /*
         * Update the model's order
         *
         * :param bool sync: Should we synchronize the change ?
         */
        if (_.isUndefined(sync)) {
            sync = true;
        }
        const requests = []
        this.each(function (model, index) {
            let order = model.get('order');
            if (order == index) {
                return;
            }
            model.set('order', index);
            if (sync) {
                const request = model.save({
                    'order': index
                }, {
                    patch: true
                }, );
                requests.push(request)
            }
        });
        return $.when(requests).then(() => this.trigger('change:reorder'))
    },
    getOrder(comp_func) {
        /*
        :param func comp_func: The function used to compare two items returning one oh them
        */
        if (this.models.length == 0) {
            return 0
        }
        return this.models.reduce(comp_func).get('order');
    },
    getMinOrder: function () {
        const comp_func = (prev, curr) => prev.get('order') < curr.get('order') ? prev : curr;
        return this.getOrder(comp_func);
    },
    getMaxOrder: function () {
        const comp_func = (prev, curr) => prev.get('order') < curr.get('order') ? curr : prev;
        return this.getOrder(comp_func);
    },
    moveUp: function (model) { // I see move up as the -1
        var index = this.indexOf(model);
        if (index > 0) {
            this.models.splice(index - 1, 0, this.models.splice(index, 1)[0]);
        }
        return this.updateModelOrder();
    },
    moveDown: function (model) {
        // I see move up as the -1
        var index = this.indexOf(model);
        if (index < this.models.length) {
            this.models.splice(index + 1, 0, this.models.splice(index, 1)[0]);
        }
        return this.updateModelOrder();
    },
    /**
     * fetch all models of the collection individually
     * 
     * @returns A Promise
     */
    syncAll() {
        var promises = [];
        this.each(function (model) {
            promises.push(model.fetch());
        });
        var resulting_deferred = $.when(...promises);
        return resulting_deferred;
    }
});
export default OrderableCollection;